package org.shunya.duplicatefileperquisitor.gui;

import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import org.shunya.duplicatefileperquisitor.model.File;
import org.shunya.duplicatefileperquisitor.model.FileGuiAttributes;
import org.shunya.duplicatefileperquisitor.searchengine.SearchEngine;

import java.nio.file.Path;
import java.text.SimpleDateFormat;
import java.util.*;

public class FileScanningService extends Service<ObservableList<File>> {

    private final Set<Path> includedPaths = new LinkedHashSet<>();
    private final Set<Path> excludedPaths = new LinkedHashSet<>();
    private final TextField filesScannedField;
    private final TextField originalFilesField;
    private final TextField duplicateFilesField;
    private final Label timeElapsedLbl;
    private final Label processingLbl;

    public FileScanningService(DuplicateFilePerquisitorController duplicateFilePerquisitorController) {
        this.filesScannedField = duplicateFilePerquisitorController.filesScannedField;
        this.originalFilesField = duplicateFilePerquisitorController.originalFilesField;
        this.duplicateFilesField = duplicateFilePerquisitorController.duplicateFilesField;
        this.timeElapsedLbl = duplicateFilePerquisitorController.timeElapsedLbl;
        processingLbl = duplicateFilePerquisitorController.processingLbl;
        for (FilePathTreeItem includePath : duplicateFilePerquisitorController.includeToScanList.getItems()) {
            includedPaths.add(includePath.getPath());
        }
        for (FilePathTreeItem excludePath : duplicateFilePerquisitorController.excludeFromScanList.getItems()) {
            excludedPaths.add(excludePath.getPath());
        }
    }

    @Override
    protected Task<ObservableList<File>> createTask() {
        return new ScannedFilesTask();
    }

    private List<File> filterFiles(List<File> originalAndDuplicateFiles, boolean includeOriginal) {
        List<File> filteredList = new ArrayList<>();
        for (File file : originalAndDuplicateFiles) {
            if (file.isOriginalFile() == includeOriginal) {
                filteredList.add(file);
            }
        }
        return filteredList;
    }

    public class ScannedFilesTask extends Task<ObservableList<File>> implements Observer {

        private String dateStart = "";
        private int allFilesCount;

        @Override
        public void update(Observable o, Object arg) {

//            if (arg instanceof FileGuiAttributes) {
//                FileGuiAttributes guiAttributes = (FileGuiAttributes) arg;
//                //updateProgress(guiAttributes.getFileNumber(), allFilesCount);
//                processingLbl.setText("Processing: " + guiAttributes.getFileName());
//            }

            String dateStop = new Date().toString();

            //HH converts hour in 24 hours format (0-23), day calculation
            SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");

            Date d1 = null;
            Date d2 = null;

            try {
                d1 = format.parse(dateStart);
                d2 = format.parse(dateStop);

                //in milliseconds
                long diff = d2.getTime() - d1.getTime();

                long diffSeconds = diff / 1000 % 60;
                long diffMinutes = diff / (60 * 1000) % 60;
                long diffHours = diff / (60 * 60 * 1000) % 24;
                long diffDays = diff / (24 * 60 * 60 * 1000);

                timeElapsedLbl.setText(diffHours + ":" + diffMinutes + ":" + diffSeconds + ":" + diff);

            } catch (Exception e) {
            }
        }

        @Override
        protected ObservableList<File> call() throws Exception {
            dateStart = new Date().toString();
            SearchEngine searchEngine = new SearchEngine(this);
            List<File> originalAndDuplicateFiles = searchEngine.findDuplicateFiles(includedPaths, excludedPaths);
            allFilesCount = searchEngine.getAllFilesCount();
            Map<Long, File> allOriginalFiles = searchEngine.getAllFiles();

            updateGui(originalAndDuplicateFiles, allOriginalFiles, dateStart);
            return FXCollections.observableList(originalAndDuplicateFiles);
        }

        private void updateGui(final List<File> originalAndDuplicateFiles, final Map<Long, File> allOriginalFiles, final String dateStart) {
            Platform.runLater(new Runnable() {
                @Override
                public void run() {

                    List<File> originalFiles = filterFiles(originalAndDuplicateFiles, true);
                    List<File> duplicateFiles = filterFiles(originalAndDuplicateFiles, false);
                    filesScannedField.setText((allOriginalFiles.size() + duplicateFiles.size()) + "");
                    originalFilesField.setText(originalFiles.size() + "");
                    duplicateFilesField.setText(duplicateFiles.size() + "");
                }
            });
        }
    }
}
